device: Fix dispose
authorCarlos Garnacho <carlosg@gnome.org>
Tue, 24 Nov 2015 16:53:41 +0000 (17:53 +0100)
committerCarlos Garnacho <carlosg@gnome.org>
Tue, 24 Nov 2015 19:52:12 +0000 (20:52 +0100)
The way master devices detach from their other master counterpart is
vulnerable to infinite recursion due to the way we first recurse on
the other device before clearing the pointer, this may happen if
that last reference to the other master device is held by the
device->associated field.

https://bugzilla.gnome.org/show_bug.cgi?id=732742

gdk/gdkdevice.c

index a1a59d27a0790f755ed85fd056c8264203dd21c1..0e325d60c3e73b068e3e8ebda4f6a24d3b17b387 100644 (file)
@@ -323,17 +323,20 @@ static void
 gdk_device_dispose (GObject *object)
 {
   GdkDevice *device = GDK_DEVICE (object);
+  GdkDevice *associated = device->associated;
 
-  if (device->type == GDK_DEVICE_TYPE_SLAVE)
-    _gdk_device_remove_slave (device->associated, device);
+  if (associated && device->type == GDK_DEVICE_TYPE_SLAVE)
+    _gdk_device_remove_slave (associated, device);
 
-  if (device->associated)
+  if (associated)
     {
-      if (device->type == GDK_DEVICE_TYPE_MASTER)
-        _gdk_device_set_associated_device (device->associated, NULL);
-
-      g_object_unref (device->associated);
       device->associated = NULL;
+
+      if (device->type == GDK_DEVICE_TYPE_MASTER &&
+          associated->associated == device)
+        _gdk_device_set_associated_device (associated, NULL);
+
+      g_object_unref (associated);
     }
 
   G_OBJECT_CLASS (gdk_device_parent_class)->dispose (object);